package atom.core3.hibernate;
/**
 * <p>Title: </p>
 * <p>Description:</p>
 * <p>Copyright: Copyright (c) 2011.12</p>
 * @author 赵明才
 * @version 1.0
 */

import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Expression;
import org.hibernate.criterion.Order;


public  class SimpleHibernateDAO implements IBaseDAO {
	/**
	 * Log4J Logger for this class
	 */
	private static final Logger logger = Logger.getLogger(SimpleHibernateDAO.class);
	
	public static SimpleHibernateDAO instance;

	public synchronized static SimpleHibernateDAO getInstance () {
		if (null == instance) instance = new SimpleHibernateDAO();
		return instance;
	}
	//通过getSession获得的session可以实现线程安全
	public Session getSession() {
		return DatabaseManager.getSession();
	}
	public Session getNewSession() {
		return DatabaseManager.getNewSession();
		
	}
	public Serializable save(Object obj)
	{
		Serializable rtn = save(obj, getSession());
		return rtn;
		
	}
	public Serializable save(Object obj, Session s) throws HibernateException {
		return s.save(obj);
	}
	
	public void delete(Object obj)
	{
			delete(obj, getSession());
		
	}
	public void delete(Object obj, Session s)
	{
		s.delete(obj);
	}
	public void update(Object obj)
	{
			update(obj, getSession());
		
	}
	public void update(Object obj, Session s)
	{
		s.update(obj);
	}
	public void saveOrUpdate(Object obj)
	{
			saveOrUpdate(obj, getSession());
		
	}
	public void saveOrUpdate(Object obj, Session s)
	{
		s.saveOrUpdate(obj);
		
	}
	public Object get(Class refClass, Serializable key,Session s)
	{
		return s.get(refClass, key);
	}
	public Object get(Class refClass, Serializable key)
	{
		return get(refClass, key,getSession());
	}
	/**
	 * Used by the base DAO classes but here for your modification
	 * Load object matching the given key and return it.
	 */
	protected Object load(Class refClass, Serializable key) throws HibernateException {
			return load(refClass, key, DatabaseManager.getSession());
	}

	/**
	 * Used by the base DAO classes but here for your modification
	 * Load object matching the given key and return it.
	 */
	protected Object load(Class refClass, Serializable key, Session s) throws HibernateException {
		return s.load(refClass, key);
	}

	/**
	 * Return all objects related to the implementation of this DAO with no filter.
	 */
	public java.util.List findAll () throws HibernateException {
			return findAll(DatabaseManager.getSession());
	}

	/**
	 * Return all objects related to the implementation of this DAO with no filter.
	 * Use the session given.
	 * @param s the Session
	 */
	public java.util.List findAll (Session s) throws HibernateException {
   		return findAll(s, getDefaultOrder());
	}

	/**
	 * Return all objects related to the implementation of this DAO with no filter.
	 */
	public java.util.List findAll (Order defaultOrder) throws HibernateException {
			return findAll(DatabaseManager.getSession(), defaultOrder);
	}

	/**
	 * Return all objects related to the implementation of this DAO with no filter.
	 * Use the session given.
	 * @param s the Session
	 */
	public java.util.List findAll (Session s, Order defaultOrder) throws HibernateException {
		Criteria crit = s.createCriteria(getReferenceClass());
		if (null != defaultOrder) crit.addOrder(defaultOrder);
		return crit.list();
	}

	/**
	 * Return all objects related to the implementation of this DAO with a filter.
	 * Use the session given.
	 * @param propName the name of the property to use for filtering
	 * @param filter the value of the filter
	 */
	protected java.util.List findFiltered (String propName, Object filter) throws HibernateException {
		return findFiltered(propName, filter, getDefaultOrder());
	}

	/**
	 * Return all objects related to the implementation of this DAO with a filter.
	 * Use the session given.
	 * @param propName the name of the property to use for filtering
	 * @param filter the value of the filter
	 * @param orderProperty the name of the property used for ordering
	 */
	protected java.util.List findFiltered (String propName, Object filter, Order order) throws HibernateException {
			return findFiltered(DatabaseManager.getSession(), propName, filter, getDefaultOrder());
	}
	
	/**
	 * Return all objects related to the implementation of this DAO with a filter.
	 * Use the session given.
	 * @param s the Session
	 * @param propName the name of the property to use for filtering
	 * @param filter the value of the filter
	 * @param orderProperty the name of the property used for ordering
	 */
	protected java.util.List findFiltered (Session s, String propName, Object filter, Order order) throws HibernateException {
		Criteria crit = s.createCriteria(getReferenceClass());
		crit.add(Expression.eq(propName, filter));
		if (null != order) crit.addOrder(order);
		return crit.list();
	}
	/**
	 * Execute a query. 
	 * @param query a query expressed in Hibernate's query language
	 * @return a distinct list of instances (or arrays of instances)
	 */
	public java.util.List find(String query) throws HibernateException {
			return find(query, DatabaseManager.getSession());
	}

	/**
	 * Perform a find but use the session given instead of creating a new one.
	 * @param query a query expressed in Hibernate's query language
	 * @s the Session to use
	 */
	public java.util.List find(String query, Session s) throws HibernateException {
		return s.createQuery(query).list();
	}

	/**
	 * Execute a query.
	 * @param query a query expressed in Hibernate's query language
	 * @return a distinct list of instances (or arrays of instances)
	 */
	public java.util.List find(String query, Object obj, org.hibernate.type.Type type) throws HibernateException {
			return find(query, obj, type, DatabaseManager.getSession());
	}

	/**
	 * Perform a find but use the session given instead of creating a new one.
	 * @param query a query expressed in Hibernate's query language
	 * @s the Session to use
	 */
	public java.util.List find(String query, Object obj, org.hibernate.type.Type type, Session s) throws HibernateException {
		return s.createQuery(query).setParameter(0, obj, type).list();
	}

	/**
	 * Execute a query.
	 * @param query a query expressed in Hibernate's query language
	 * @return a distinct list of instances (or arrays of instances)
	 */
	public java.util.List find(String query, Object[] obj, org.hibernate.type.Type[] type) throws HibernateException {
			return find(query, obj, type, DatabaseManager.getSession());
	}

	/**
	 * Perform a find but use the session given instead of creating a new one.
	 * @param query a query expressed in Hibernate's query language
	 * @s the Session to use
	 */
	public java.util.List find(String query, Object[] obj, org.hibernate.type.Type[] type, Session s) throws HibernateException {
		return s.createQuery(query).setParameters(obj, type).list();
	}
	
	/**
	 * Execute a query. 
	 * @param queryStr a query expressed in Hibernate's query language
	 * @return a distinct list of instances (or arrays of instances)
	 */
	public Query getQuery(String queryStr) throws HibernateException {
			return getQuery(queryStr, DatabaseManager.getSession());
	}

	/**
	 * Execute a query but use the session given instead of creating a new one.
	 * @param queryStr a query expressed in Hibernate's query language
	 * @s the Session to use
	 */
	public Query getQuery(String queryStr, Session s) throws HibernateException {
		return s.createQuery(queryStr);
	}



	/**
	 * Execute a query. 
	 * @param query a query expressed in Hibernate's query language
	 * @param queryStr the name of a query defined externally 
	 * @param param the first parameter to set
	 * @return Query
	 */
	protected Query getQuery(String queryStr, Serializable param) throws HibernateException {
			return getQuery(queryStr, param, DatabaseManager.getSession());
	}

	/**
	 * Execute a query but use the session given instead of creating a new one.
	 * @param queryStr a query expressed in Hibernate's query language
	 * @param param the first parameter to set
	 * @s the Session to use
	 * @return Query
	 */
	protected Query getQuery(String queryStr, Serializable param, Session s) throws HibernateException {
		Query q = getQuery(queryStr, s);
		q.setParameter(0, param);
		return q;
	}

	/**
	 * Execute a query. 
	 * @param queryStr a query expressed in Hibernate's query language
	 * @param params the parameter array
	 * @return Query
	 */
	protected Query getQuery(String queryStr, Serializable[] params) throws HibernateException {
			return getQuery(queryStr, params, DatabaseManager.getSession());
	}

	/**
	 * Execute a query but use the session given instead of creating a new one.
	 * @param queryStr a query expressed in Hibernate's query language
	 * @param params the parameter array
	 * @s the Session
	 * @return Query
	 */
	protected Query getQuery(String queryStr, Serializable[] params, Session s) throws HibernateException {
		Query q = getQuery(queryStr, s);
		if (null != params) {
			for (int i = 0; i < params.length; i++) {
				q.setParameter(i, params[i]);
			}
		}
		return q;
	}

	/**
	 * Obtain an instance of Query for a named query string defined in the mapping file.
	 * Use the parameters given.
	 * @param queryStr a query expressed in Hibernate's query language
	 * @param params the parameter Map
	 * @return Query
	 */
	protected Query getQuery(String queryStr, Map params) throws HibernateException {
			return getQuery(queryStr, params, DatabaseManager.getSession());
	}

	/**
	 * Obtain an instance of Query for a named query string defined in the mapping file.
	 * Use the parameters given and the Session given.
	 * @param queryStr a query expressed in Hibernate's query language
	 * @param params the parameter Map
	 * @s the Session
	 * @return Query
	 */
	protected Query getQuery(String queryStr, Map params, Session s) throws HibernateException {
		Query q = getQuery(queryStr, s);
		if (null != params) {
			for (Iterator i=params.entrySet().iterator(); i.hasNext(); ) {
				Map.Entry entry = (Map.Entry) i.next();
				q.setParameter((String) entry.getKey(), entry.getValue());
			}
		}
		return q;
	}
	/**
	 * Obtain an instance of Query for a named query string defined in the mapping file.
	 * @param name the name of a query defined externally 
	 * @return Query
	 */
	protected Query getNamedQuery(String name) throws HibernateException {
			return getNamedQuery(name, DatabaseManager.getSession());
	}

	/**
	 * Obtain an instance of Query for a named query string defined in the mapping file.
	 * Use the session given.
	 * @param name the name of a query defined externally 
	 * @param s the Session
	 * @return Query
	 */
	protected Query getNamedQuery(String name, Session s) throws HibernateException {
		Query q = s.getNamedQuery(name);
		return q;
	}

	/**
	 * Obtain an instance of Query for a named query string defined in the mapping file.
	 * @param name the name of a query defined externally 
	 * @param param the first parameter to set
	 * @return Query
	 */
	protected Query getNamedQuery(String name, Serializable param) throws HibernateException {
			return getNamedQuery(name, param, DatabaseManager.getSession());
	}

	/**
	 * Obtain an instance of Query for a named query string defined in the mapping file.
	 * Use the session given.
	 * @param name the name of a query defined externally 
	 * @param param the first parameter to set
	 * @param s the Session
	 * @return Query
	 */
	protected Query getNamedQuery(String name, Serializable param, Session s) throws HibernateException {
		Query q = s.getNamedQuery(name);
		q.setParameter(0, param);
		return q;
	}

	/**
	 * Obtain an instance of Query for a named query string defined in the mapping file.
	 * Use the parameters given.
	 * @param name the name of a query defined externally 
	 * @param params the parameter array
	 * @return Query
	 */
	protected Query getNamedQuery(String name, Serializable[] params) throws HibernateException {
			return getNamedQuery(name, params, DatabaseManager.getSession());
	}

	/**
	 * Obtain an instance of Query for a named query string defined in the mapping file.
	 * Use the parameters given and the Session given.
	 * @param name the name of a query defined externally 
	 * @param params the parameter array
	 * @s the Session
	 * @return Query
	 */
	protected Query getNamedQuery(String name, Serializable[] params, Session s) throws HibernateException {
		Query q = s.getNamedQuery(name);
		if (null != params) {
			for (int i = 0; i < params.length; i++) {
				q.setParameter(i, params[i]);
			}
		}
		return q;
	}

	/**
	 * Obtain an instance of Query for a named query string defined in the mapping file.
	 * Use the parameters given.
	 * @param name the name of a query defined externally 
	 * @param params the parameter Map
	 * @return Query
	 */
	protected Query getNamedQuery(String name, Map params) throws HibernateException {
			return getNamedQuery(name, params, DatabaseManager.getSession());
	}

	/**
	 * Obtain an instance of Query for a named query string defined in the mapping file.
	 * Use the parameters given and the Session given.
	 * @param name the name of a query defined externally 
	 * @param params the parameter Map
	 * @s the Session
	 * @return Query
	 */
	protected Query getNamedQuery(String name, Map params, Session s) throws HibernateException {
		Query q = s.getNamedQuery(name);
		if (null != params) {
			for (Iterator i=params.entrySet().iterator(); i.hasNext(); ) {
				Map.Entry entry = (Map.Entry) i.next();
				q.setParameter((String) entry.getKey(), entry.getValue());
			}
		}
		return q;
	}
	
	/**
	 * 执行HQL进行查询
	 * @param query a query expressed in Hibernate's query language
	 * @s the Session to use
	 */
	public java.util.List executeHQL(String hql, Map params, int offset,int length, Session s) throws HibernateException {
		if (logger.isDebugEnabled()) {
			logger.debug("要执行的HQL查询语句是:" + hql);
			logger.debug("要执行的HQL查询的参数列表是：" +  params.toString());
		}

		Query query = getQuery(hql, params, s);
		if (offset > 0)	query.setFirstResult(offset);
		if (length > 0) query.setMaxResults(length);
		return query.list();
	}	

	/**
	 * 执行HQL进行查询
	 * @param query a query expressed in Hibernate's query language
	 * @s the Session to use
	 */
	public java.util.List executeHQL(String hql, Map params, int offset,int length) throws HibernateException {
			return executeHQL(hql, params, offset, length, DatabaseManager.getSession());
	}
	/**
	 * 执行HQL条件查询出记录数
	 * @param query a query expressed in Hibernate's query language
	 * @s the Session to use
	 */
	public int getCountFromHQL(String hql, Map params, Session s) throws HibernateException {
		if (logger.isDebugEnabled()) {
			logger.debug("要执行的HQL查询语句是:" + hql);
			logger.debug("要执行的HQL查询的参数列表是：" +  params.toString());
		}

		Query query = getQuery(hql, params, s);
		List list = query.list();
		if (0 == list.size()) return 0;
		return ((Integer)list.get(0)).intValue();
	}

	
	/**
	 * 执行HQL条件查询出记录数
	 * @param query a query expressed in Hibernate's query language
	 * @s the Session to use
	 */
	public int getCountFromHQL(String hql, Map params) throws HibernateException {
			return getCountFromHQL(hql, params, DatabaseManager.getSession());
	}

	/**
	 * 执行HQL条件查询出总数
	 * @param query a query expressed in Hibernate's query language
	 * @s the Session to use
	 */
	public double getSumFromHQL(String hql, Map params, Session s) throws HibernateException {
		if (logger.isDebugEnabled()) {
			logger.debug("要执行的HQL查询语句是:" + hql);
			logger.debug("要执行的HQL查询的参数列表是：" +  params.toString());
		}

		Query query = getQuery(hql, params, s);
		List list = query.list();
		if (0 == list.size()) return 0;
		Double value = (Double)list.get(0);
		if (null == value) return 0;
		return value.doubleValue();
	}

	/**
	 * 执行HQL条件查询出记录数
	 * @param query a query expressed in Hibernate's query language
	 * @s the Session to use
	 */
	public double getSumFromHQL(String hql, Map params) throws HibernateException {
			return getSumFromHQL(hql, params, DatabaseManager.getSession());
	}
	protected Order getDefaultOrder () {
		return null;
	}
	//protected abstract Class getReferenceClass();
	protected  Class getReferenceClass()
	{
		return null;
	}
}
